package com.mvw.tetrominoes.util {
	
	import flash.events.TimerEvent;
	import flash.utils.Timer;
	
	/**
	 * An abstract representation of gravity as implemented by a Timer and single
	 * action to be taken upon gravitational force inititiation.
	 */
	public class Gravity {
		
		private var timer:Timer;
		private var pulling:Boolean;
		
		/**
		 * The constructor defines gravity as an instance of a Timer.
		 */
		public function Gravity():void {
			this.timer = new Timer(1000,1);
			this.timer.addEventListener(TimerEvent.TIMER, onTimerEvent);
			this.pulling = false;
		}
		
		/**
		 * Resets the Timer.
		 * 
		 * @param event An instance of TimerEvent.
		 */
		private function onTimerEvent(event:TimerEvent):void {
			this.reset();
		} 
		
		/**
		 * Resets gravity.
		 */
		private function reset():void {
			this.timer.reset();
			this.timer.start();
		}
		
		/**
		 * Initiates gravity.
		 */
		public function initiate():void {
			this.timer.start();
		}
		
		/**
		 * Adds an action to be taken regularly while gravity is active.
		 * 
		 * @param handler A functional representation of an action governed by gravity.
		 *
		 */
		public function setAction(handler:Function):void {
			if (!this.pulling) {
				this.timer.addEventListener(TimerEvent.TIMER, handler);
				this.pulling = true;
				this.reset();
			}
			else {
				throw new Error("Only 1 action currently supported by Gravity.");
			}
		}
		
		/**
		 * Clears an action from the effect of gravity.
		 * 
		 * @param handler A functional representation of an action governed by gravity.
		 */
		public function clearAction(handler:Function):void {
			this.timer.removeEventListener(TimerEvent.TIMER, handler);
			this.pulling = false;
			this.reset();
		}
		
		/**
		 * Indicates whether gravity is currently pulling and affecting governed objects.
		 * 
		 * @return An instance of Boolean.
		 */
		public function isPulling():Boolean {
			return this.pulling;
		}
		
	}
}